/*
 * @Descripttion: 业务数据缓存
 * @version: 1.0
 * @LastEditors: lzt
 * @LastEditTime: 2023-11-25
 */

import tool from '@/utils/tool';
import api from "@/api";
import http from "@/utils/request";
import {h} from "vue";
import {ElButton, ElTag} from "element-plus";
import store from "@/store";
import constant from "@/constant";
import db from "@/utils/db";

const cache = {}


function lockKey(dataKey) {
    return "LOCK_" + dataKey;
}

function urlKey(dataKey) {
    return "URL_" + dataKey;
}

function storeKey(key, params) {
    //获取请求参数的MD5值作为缓存key的后缀
    let paramArray = [];
    for (let param in params) {
        paramArray.push(param);
    }
    if (paramArray.length > 0) {
        paramArray = paramArray.sort();
        let tempStr = "";
        paramArray.forEach(item => {
            tempStr = tempStr + item + params[item];
        })
        let cryptoKey = tool.crypto.MD5(tempStr);
        return key + "_" + cryptoKey;
    }
    return key;
}

function urlData(name, url, params) {
    return {name: name, url: url, params: params};
}

async function cacheTreeData(cacheKey, data) {
	tool.data.remove(cacheKey);
	let dbName = "masterDB";
	let tableName = "TREE_TABLE";
	let storeData = {cacheKey: cacheKey, content: tool.toJsonString(data)}
	let treeDatabase = await db.open(dbName);
	await treeDatabase.delete(tableName, cacheKey);
	await treeDatabase.add(tableName, storeData);
	treeDatabase.close();
	tool.data.set(cacheKey,true);
}

async function getTreeData(cacheKey) {
	let dbName = "masterDB";
	let tableName = "TREE_TABLE";
	let treeDatabase = await db.open(dbName);
	let data = await treeDatabase.get(tableName, cacheKey);
	treeDatabase.close();
	if(data){
		return tool.toObj(data.content);
	}
	return null;
}

async function clearTreeData(cacheKey) {
	let dbName = "masterDB";
	let tableName = "TREE_TABLE";
	let treeDatabase = await db.open(dbName);
	await treeDatabase.delete(tableName, cacheKey);
	treeDatabase.close();
	tool.data.remove(cacheKey);
}

cache.timer = {
    //开启缓存数据过期检测处理,10秒执行一次
    start: function () {
        setInterval(() => {
            cache.dic.expiredProcess();
            cache.tree.expiredProcess();
        }, 10 * 1000);
    },
    //清除所有定时任务
    stop: function () {
        let timerId = setInterval(() => {
        }, 10000);
        for (let i = 1; i <= timerId; i++) {
            clearInterval(i);
        }
    }
}

cache.dic = {
    //字典存储key的前缀
    PREFIX: "DICT_",
    //缓存过期时间，单位秒，0代表不过期
    expired: 0,
    //发送请求
    sendRequest: function (req, params) {
        req.post(params).then((rsp) => {
            this.storeData(rsp, req.url, params);
        });
    },
    //存储数据
    storeData: function (rsp, url, params) {
        if (rsp.success && rsp.data) {
            let alreadyRemoveKeys = [];
			let count = 0;
            rsp.data.forEach(item => {
				if(count>1500){
					return ;
				}
                //缓存key
                let key = this.PREFIX + item.dictionaryCode;

                //如果当前key是第一次循环时的操作
                if (!alreadyRemoveKeys.includes(key)) {
                    //不管之前有没有数据，清空此key的缓存数据
                    tool.data.remove(key);
                    //把key放入已清空标识，后续循环不再进行请空处理
                    alreadyRemoveKeys.push(key);
                    //把该数据的请求地址和参数放入缓存，供后续自动更新缓存使用
                    params.dictionaryCode = item.dictionaryCode
                    tool.data.set(urlKey(key), urlData(item.dictionaryCode, url, params));
                }

                //从缓存中获取已缓存数据
                let data = tool.data.get(key);
                //第一次放时初始化对象类型
                if (!data) {
                    data = [];
                }
                //添加新成员重新放入缓存
				let tempItem = {};
				tempItem.k = item.dictionaryValue;
				tempItem.v = item.dictionaryRelValue;
				tempItem.n = item.dictionaryLabel;
				tempItem.e = item.isEnabled;
				if(item.color){
					tempItem.c = item.color;
				}

                data.push(tempItem);
                //重新放置缓存
                tool.data.set(key, data, this.expired);
				count++;
            });
        }
    },
    //重新加载单类数据字典
    reload: async function (dictionaryCode) {
        let key = this.PREFIX + dictionaryCode;
        let urlData = tool.data.get(urlKey(key));
        //存在请求地址，则进行刷新操作
        if (urlData) {
            //检查此操作是否加锁，加锁直接返回
            let lock = tool.data.get(lockKey(key));
            //存在锁时，直接返回
            if (lock) {
                return null;
            }
            //加锁进行数据刷新处理，10秒未处理完，自动解锁
            tool.data.set(lockKey(key), true, 10);
            let params = {dictionaryCode: dictionaryCode};
            let rsp = await http.post(urlData.url, urlData.params);
            this.storeData(rsp, urlData.url, urlData.params);
            //数据处理完成，释放锁
            tool.data.remove(lockKey(key));
            //重新请求之后再从缓存获取一次（因为请求为异步处理，暂时无效）
            return tool.data.get(key);
        }
        return null;
    },
    //key过期处理
    expiredProcess: function () {
        for (let key in localStorage) {
            if (key.startsWith(this.PREFIX)) {
                let data = tool.data.get(key);
                if (!data) {
                    let urlData = tool.data.get(urlKey(key));
                    if (urlData) {
                        this.reload(urlData.params.dictionaryCode);
                    }
                }
            }
        }
    },
    options: function (dictionaryCode, isPriKey) {
        let key = this.PREFIX + dictionaryCode;
        let data = tool.data.get(key);
        //没获取到数据，重新请求加载数据
        if (!data || !Array.isArray(data)) {
            data = this.reload(dictionaryCode);
        }
        if (data&&Array.isArray(data)) {
            let ops = [];
            data.forEach(item => {
                if (item.e === '1' && item.v) {
                    let option = {};
                    option.label = item.n;
                    if (isPriKey) {
                        option.value = item.k;
                    } else {
                        option.value = item.v;
                    }
                    ops.push(option);
                }
            });
            return ops;
        } else {
            return [];
        }
    },
    flows: function (dictionaryCode, flowGroupId) {
        let key = this.PREFIX + dictionaryCode;
        let data = tool.data.get(key);
        //没获取到数据，重新请求加载数据
        if (!data || !Array.isArray(data)) {
            data = this.reload(dictionaryCode);
        }
        if (data&&Array.isArray(data)) {
            let ops = [];
            data.forEach(item => {
                if (item.e === '1' && item.v===flowGroupId) {
                    let option = {};
                    option.label = item.n;
                    option.value = item.v;
                    ops.push(option);
                }
            });
            return ops;
        } else {
            return [];
        }
    },
    toOptions: function (data, isPriKey) {
        if (data&&Array.isArray(data)) {
            let ops = [];
            data.forEach(item => {
                if (item.isEnabled === '1' && item.dictionaryCodeValue) {
                    let option = {};
                    option.label = item.dictionaryLabel;
                    if (isPriKey) {
                        option.value = item.dictionaryValue;
                    } else {
                        option.value = item.dictionaryCodeValue;
                    }
                    ops.push(option);
                }
            });
            return ops;
        } else {
            return [];
        }
    },
    show: function (dictionaryCode, value, bool) {
		if (value === '0000000') {
			return '顶级';
		}
		if (value === '00000000-0000-0000-0000-000000000000') {
			return '未知';
		}
		if (dictionaryCode && value) {
			let key = this.PREFIX + dictionaryCode;
			let data = tool.data.get(key);
			//没获取到数据，重新请求加载数据
			if (!data || !Array.isArray(data)) {
				data = this.reload(dictionaryCode);
			}
			// if (!Array.isArray(data)) {
			// 	data = [];
			// 	let url = tool.data.get(dictionaryCode + "_ID_API_URL");
			// 	if (url) {
			// 		console.log(url);
			// 		let rsp = await http.post(url + "/" + value, {});
			// 		if (rsp.code === 2000 && rsp.data) {
			// 			let tempItem = {};
			// 			tempItem.k = rsp.data.dictionaryValue;
			// 			tempItem.v = rsp.data.dictionaryRelValue;
			// 			tempItem.n = rsp.data.dictionaryLabel;
			// 			tempItem.e = rsp.data.isEnabled;
			// 			if (rsp.data.color) {
			// 				tempItem.c = rsp.data.color;
			// 			}
			// 			data.push(tempItem);
			// 		}
			// 		console.log(data);
			// 	}
			// }
			if (data && Array.isArray(data)) {
				data.forEach(item => {
					if (item.v === value || item.k === value) {
						value = item.n;
						if (bool && item.c) {
							let label = value;
							value = h(ElTag, {style: "color:#fff;background-color: " + item.c + "9D;border: " + item.c}, () => label);
						}
					}
				});
			}
		}
		return value;
	},
    //初始化数据字典
    init: function () {
        this.initEntityGroup();
        this.authInit();
    },
    initEntityGroup() {
        let dictionaryCode = "ENTITY_DICT";
        let key = this.PREFIX + dictionaryCode;
        tool.data.remove(key);
        let data = [];
        for (let item in constant.entity) {
            let dict = {};
            dict.k = constant.entity[item].name;
            dict.v = constant.entity[item].name;
            dict.n = constant.entity[item].label;
            dict.d = dictionaryCode;
            dict.e = "1";
            data.push(dict);
        }
        tool.data.set(key, data);
    },
    authInit() {
        for (let module in api) {
            if ((api[module] instanceof Object) && !Array.isArray(api[module])) {
                for (let entity in api[module]) {
                    if ((api[module][entity] instanceof Object) && !Array.isArray(api[module][entity])) {
                        if(api[module][entity]['dataDictionaries']){
                            this.sendRequest(api[module][entity]['dataDictionaries'], {});
                        }
                        if(api[module][entity]['treeData']&&api[module][entity]['treeData'].storeName){
                            tool.data.set(api[module][entity]['treeData'].storeName+"_TREE_API_URL", api[module][entity]['treeData'].url);
                        }
						if(api[module][entity]['findById']&&api[module][entity]['findById'].storeName){
							tool.data.set(api[module][entity]['findById'].storeName+"_ID_API_URL", api[module][entity]['findById'].url);
						}
                    }
                }
            }
        }
    },
}

cache.tree = {
    //缓存key的前缀
    PREFIX: "TREE_",
    //缓存过期时间，单位秒，0代表不过期
    expired: 0,
    //发送请求
    sendRequest: async function (name, url, params) {
        if (url && params) {
            let rsp = await http.post(url, params);
            await this.storeData(rsp, name, url, params);
            return rsp.data;
        }
        return null;
    },
    //存储数据
    storeData: async function (rsp, name, url, params) {
		if (rsp.success && rsp.data) {
			let key = this.PREFIX + name;
			let cacheKey = storeKey(key, params)
			//不管之前有没有数据，请清空此key的缓存数据
			// tool.data.remove(cacheKey);
			//放入最新请求的数据
			// tool.data.set(cacheKey, rsp.data, this.expired);
			await cacheTreeData(cacheKey,rsp.data);
			//把该数据的请求地址和参数放入缓存，供后续自动更新缓存使用
			tool.data.set(urlKey(cacheKey), urlData(name, url, params));
		}
	},
    //重新加载单类数据字典
    reload: async function (name, params) {
        //缓存名称为空，直接返回
        if (!name) {
            return null;
        }
        let url = tool.data.get(name+"_TREE_API_URL");
        if(!url){
            return null;
        }
        let key = this.PREFIX + name;
        //如果参数为空，则从缓存中获取url和参数的信息，重新加载
        if (!params) {
            for (let cacheKey in localStorage) {
                if (cacheKey.startsWith(key)) {
                    let urlData = tool.data.get(urlKey(cacheKey));
                    if (urlData) {
                        urlData.params.toServer = true;
                        this.reload(name, urlData.params);
                    }
                }
            }
            return null;
        }
        //判断是否需要从服务器加载数据
        let needClearData = false;
        if (params.toServer) {
            needClearData = true;
            delete params.toServer;
        }

        //获取请求参数的MD5值作为缓存key的后缀
        let cacheKey = storeKey(key, params);
        //如果需要从服务器加载数据，则先删除缓存数据
        if (needClearData) {
            // tool.data.remove(cacheKey);
			await clearTreeData(cacheKey);
        }

        //先从缓存获取数据
        // let data = tool.data.get(cacheKey);
		let data = await getTreeData(cacheKey);
        //获取到数据直接返回
        if (data) {
            return data;
        }

        //缓存无数据，向服务器发起请求
        //检查此操作是否加锁，加锁直接返回
        let lock = tool.data.get(lockKey(cacheKey));
        //存在锁时，直接返回
        if (lock) {
			//暂时不返回空
            return null;
        }
        //加锁进行数据刷新处理，10秒未处理完，自动解锁
        tool.data.set(lockKey(cacheKey), true, 10);
        let result = await this.sendRequest(name, url, params);
        tool.data.remove(lockKey(cacheKey));
        return result;
    },
    options: async function (name, params) {
        let data = await this.reload(name, params);
        if (data) {
            this.addDisabled(data);
        }
        return data;
    },
    addDisabled(data) {
		if(Array.isArray(data)){
			data.forEach(item => {
				item.disabled = item.isEnabled !== '1';
				if (item.children) {
					this.addDisabled(item.children);
				}
			})
		}
    },
	clear:function(name){
		for (let cacheKey in localStorage) {
			if (cacheKey.startsWith(this.PREFIX)&&cacheKey.includes(name)) {
				// tool.data.remove(cacheKey);
				clearTreeData(cacheKey);
			}
		}
	},
    //key过期处理
    expiredProcess: function () {
        for (let cacheKey in localStorage) {
            if (cacheKey.startsWith(this.PREFIX)) {
                let data = tool.data.get(cacheKey);
                if (!data) {
                    let urlData = tool.data.get(urlKey(cacheKey));
                    if (urlData) {
                        this.reload(urlData.name);
                    }
                }
            }
        }
    },
}

cache.data = {
	//缓存key的前缀
	PREFIX: "CACHE_DATA_",
	//缓存过期时间，单位秒，0代表不过期
	expired: 0,
	//发送请求
	sendRequest: async function (name, url, params) {
		if (url && params) {
			let rsp = await http.post(url, params);
			this.storeData(rsp, name, url, params);
			return rsp.data;
		}
		return null;
	},
	//存储数据
	storeData: function (rsp, name, url, params) {
		if (rsp.success && rsp.data) {
			let key = this.PREFIX + name;
			let cacheKey = storeKey(key, params)
			//不管之前有没有数据，请清空此key的缓存数据
			tool.data.remove(cacheKey);
			//放入最新请求的数据
			tool.data.set(cacheKey, rsp.data, this.expired);
			//把该数据的请求地址和参数放入缓存，供后续自动更新缓存使用
			tool.data.set(urlKey(cacheKey), urlData(name, url, params));
		}
	},
	//重新加载单类数据字典
	reload: async function (name, url, params) {
		//缓存名称为空，直接返回
		if (!name) {
			return null;
		}

		let key = this.PREFIX + name;
		//如果url或参数为空，则从缓存中获取url和参数的信息，重新加载
		if (!url || !params) {
			for (let cacheKey in localStorage) {
				if (cacheKey.startsWith(key)) {
					let urlData = tool.data.get(urlKey(cacheKey));
					if (urlData) {
						urlData.params.toServer = true;
						this.reload(name, urlData.url, urlData.params);
					}
				}
			}
			return null;
		}
		//判断是否需要从服务器加载数据
		let needClearData = false;
		if (params.toServer) {
			needClearData = true;
			delete params.toServer;
		}

		//获取请求参数的MD5值作为缓存key的后缀
		let cacheKey = storeKey(key, params);
		//如果需要从服务器加载数据，则先删除缓存数据
		if (needClearData) {
			tool.data.remove(cacheKey);
		}

		//先从缓存获取数据
		let data = tool.data.get(cacheKey);
		//获取到数据直接返回
		if (data) {
			return data;
		}

		//缓存无数据，向服务器发起请求
		//检查此操作是否加锁，加锁直接返回
		let lock = tool.data.get(lockKey(cacheKey));
		//存在锁时，直接返回
		if (lock) {
			return null;
		}
		//加锁进行数据刷新处理，10秒未处理完，自动解锁
		tool.data.set(lockKey(cacheKey), true, 10);
		let result = await this.sendRequest(name, url, params);
		tool.data.remove(lockKey(cacheKey));
		return result;
	},
	//key过期处理
	expiredProcess: function () {
		for (let cacheKey in localStorage) {
			if (cacheKey.startsWith(this.PREFIX)) {
				let data = tool.data.get(cacheKey);
				if (!data) {
					let urlData = tool.data.get(urlKey(cacheKey));
					if (urlData) {
						this.reload(urlData.name);
					}
				}
			}
		}
	},
	loadColumnGroups:async function () {
		//查询所有字段信息
		let columns = await this.reload("FamsColumns", api.asset.column.all.url, {isGroup: '0'});
		let columnGroups = [];
		if(columns){
			columns.forEach((column, position) => {
				//字段样式的默认属性
				let columnStyle = {
					columnId: column.id,
					isReadonly: '0',
					isRequired: '0',
					colSpan: 0,
					minValue: 0,
					minLength: 0,
					groupPosition: position,
					defaultValue: null,
					visible: true,
				};
				Object.assign(column, columnStyle);

				let columnGroup = columnGroups.filter(group => group.levelCode === column.parentLevelCode)[0];
				if (columnGroup) {
					columnGroup.items.push(column)
				} else {
					columnGroup = {levelCode: column.parentLevelCode, items: []};
					columnGroup.items.push(column)
					columnGroups.push(columnGroup);
				}
			});
		}
		return columnGroups;
	},
	loadGlobalParam:async function (paramCode) {
		let key = this.PREFIX+"SysGlobalParam" + paramCode;
		//先从缓存获取数据
		let data = tool.data.get(key);
		//获取到数据直接返回
		if (data) {
			return data;
		}
		let res = await api.system.globalParam.load.post({});
		if (res.code === 2000) {
			let params = res.data;
			if (Array.isArray(params)) {
				params.forEach(item => {
					item.paramValue = tool.toObj(item.paramValue);
					tool.data.set(this.PREFIX+"SysGlobalParam" + item.paramCode,item.paramValue);
				});
			}
		}
		return null;
	},
	loadDataCard:async function (cardId) {
		let key = this.PREFIX+"FamsAssetCard" + cardId;
		//先从缓存获取数据
		let data = tool.data.get(key);
		//获取到数据直接返回
		if (data) {
			return data;
		}
		let rsp = await api.asset.card.findById.post({id: cardId});
		if (rsp.code === 2000) {
			tool.data.set(key,rsp.data);
			return rsp.data;
		}
		return null;
	},
    loadAssetCategory:async function (assetCategoryId) {
        let key = this.PREFIX+"FamsAssetCategory" + assetCategoryId;
        //先从缓存获取数据
        let data = tool.data.get(key);
        //获取到数据直接返回
        if (data) {
            return data;
        }
        let rsp = await api.asset.assetcategory.findById.post({id: assetCategoryId});
        if (rsp.code === 2000) {
            tool.data.set(key,rsp.data);
            return rsp.data;
        }
        return null;
    },
	loadDocumentConfig:async function (configId) {
		let key = this.PREFIX+"FamsDocumentConfig" + configId;
		//先从缓存获取数据
		let data = tool.data.get(key);
		//获取到数据直接返回
		if (data) {
			return data;
		}
		let rsp = await api.asset.documentConfig.findById.post({id: configId});
		if (rsp.code === 2000) {
			tool.data.set(key,rsp.data);
			return rsp.data;
		}
		return null;
	},
	clear:function(name){
		for (let cacheKey in localStorage) {
			if (cacheKey.startsWith(this.PREFIX)&&cacheKey.includes(name)) {
				console.log("cache.data.clear",name);
				tool.data.remove(cacheKey);
			}
		}
		if("SysGlobalParam"===name){
			this.loadGlobalParam("_ALL");
		}
	},
}

export default cache
